package com.imagination.applet.controller.web.configuration;

import com.google.common.collect.Maps;
import com.imagination.applet.infrastructure.common.RestResponse;
import com.imagination.applet.infrastructure.utils.JwtUtils;
import com.imagination.applet.infrastructure.utils.ObjectMapperUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.UUID;

public class WeChatAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public WeChatAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher("/wx/login", "POST"));
        super.setAuthenticationManager(authenticationManager);

    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String weChatCode = request.getParameter("code");
        String shareCode = request.getParameter("shareCode");
        if (weChatCode == null) {
            throw new AuthenticationServiceException("WeChat code not provided");
        }
        return getAuthenticationManager().authenticate(new WeChatAuthenticationToken(weChatCode, shareCode));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        if (authResult instanceof JwtToken token) {
            String weChatCode = request.getParameter("code");
            String newToken = JwtUtils.createToken(UUID.randomUUID().toString(), "WX Login", buildClaims(token), 365 * 30 * 24 * 3600000L);
            String refreshToken = JwtUtils.createToken(UUID.randomUUID().toString(), "WX Login Refresh", buildClaims(token), 365 * 30 * 24 * 3600000L);
            PrintWriter out = response.getWriter();
            response.setContentType("text/html;charset = UTF-8");
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            out.print(buildBody(weChatCode, newToken, refreshToken));
            out.flush();
        }
    }

    private String buildBody(String code, String token, String refreshToken) {
        Map<String, Object> body = Maps.newHashMap();
        body.put("code", code);
        body.put(SecurityConstant.TOKEN, token);
        body.put(SecurityConstant.REFRESH_TOKEN, refreshToken);
        System.out.println("登陆返回参数" + body.toString());
        return ObjectMapperUtils.write(RestResponse.ok(body));
    }

    private Map<String, Object> buildClaims(JwtToken token) {
        Map<String, Object> claims = Maps.newHashMap();
        claims.put(JwtToken.USER_ID, token.getUserId());
        claims.put(JwtToken.OPEN_ID, token.getOpenId());
        claims.put(JwtToken.OPEN_ID_TYPE, token.getOpenIdType());
        claims.put(JwtToken.ACCESS_KEY, token.getAccessKey());
        return claims;
    }
}
